package com.opencee.cloud.core.security;

import com.opencee.common.security.SecurityProperties;
import com.opencee.common.security.oauth2.CustomJwtTokenServices;
import com.opencee.common.security.oauth2.CustomJwtUserAuthenticationConverter;
import com.opencee.common.security.oauth2.CustomUserAuthenticationConverter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.util.Assert;

import java.util.Collection;

/**
 * 认证信息帮助类
 *
 * @author liuyadu
 */
@Slf4j
public class SecurityUtils {



    /**
     * 构建token转换器
     *
     * @return
     */
    public static DefaultAccessTokenConverter buildAccessTokenConverter() {
        CustomUserAuthenticationConverter userAuthenticationConverter = new CustomUserAuthenticationConverter();
        DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
        accessTokenConverter.setUserTokenConverter(userAuthenticationConverter);
        return accessTokenConverter;
    }

    /**
     * 构建jwtToken转换器
     *
     * @return
     */
    public static JwtAccessTokenConverter buildJwtTokenConverter(SecurityProperties properties) throws Exception {
        // 使用自定义系统用户凭证转换器
        CustomJwtUserAuthenticationConverter userAuthenticationConverter = new CustomJwtUserAuthenticationConverter(properties.getJwtClaimsAesKey());
        DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
        accessTokenConverter.setUserTokenConverter(userAuthenticationConverter);
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(properties.getJwtSigningKey());
        converter.setAccessTokenConverter(accessTokenConverter);
        converter.afterPropertiesSet();
        return converter;
    }


    /**
     * 构建资源服务器JwtToken服务类
     *
     * @return
     */
    public static ResourceServerTokenServices buildJwtTokenServices(SecurityProperties properties) throws Exception {
        CustomJwtTokenServices tokenServices = new CustomJwtTokenServices();
        // 这里的签名key 保持和认证中心一致
        JwtAccessTokenConverter converter = buildJwtTokenConverter(properties);
        JwtTokenStore jwtTokenStore = new JwtTokenStore(converter);
        tokenServices.setTokenStore(jwtTokenStore);
        tokenServices.setJwtAccessTokenConverter(converter);
        tokenServices.setDefaultAccessTokenConverter((DefaultAccessTokenConverter) converter.getAccessTokenConverter());
        log.info("buildJwtTokenServices[{}]", tokenServices);
        return tokenServices;
    }

    /**
     * 构建jwtTokenStore
     *
     * @return
     * @throws Exception
     */
    public static TokenStore buildJwtTokenStore(SecurityProperties properties) throws Exception {
        // 这里的签名key 保持和认证中心一致
        JwtAccessTokenConverter converter = buildJwtTokenConverter(properties);
        JwtTokenStore jwtTokenStore = new JwtTokenStore(converter);
        return jwtTokenStore;
    }



    /**
     * 根据客户端和用户名删除token
     *
     * @param tokenStore
     * @param clientId
     * @param username
     */
    public static void removeTokensByClientIdAndUserName(TokenStore tokenStore, String clientId, String username) {
        Assert.notNull(tokenStore, "tokenStore不能为空");
        Assert.notNull(clientId, "客户端ID不能为空");
        Assert.notNull(username, "用户名不能为空");
        // 动态更新客户端生成的token
        Collection<OAuth2AccessToken> accessTokens = tokenStore.findTokensByClientIdAndUserName(clientId, username);
        if (accessTokens != null && !accessTokens.isEmpty()) {
            for (OAuth2AccessToken accessToken : accessTokens) {
                tokenStore.removeAccessToken(accessToken);
            }
        }
    }
}
